/*
Copyright (C) 2008 Björn Augustsson, oggust@gmail.com
Copyright (C) 2008 Olaf Klein, o.b.klein@gpsbabel.org
- Copyright (C) 2005 Robert Lipe, robertlipe@usa.net
+ Copyright (C) 2005-2013 Robert Lipe, robertlipe@gpsbabel.org
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include <ctype.h>
#include <math.h>
#include <string.h>
+#include <QtCore/QMap.h>
+
#include "defs.h"
-#include "avltree.h"
#define MYNAME "humminbird"
#define RTE_NAME_LEN 20
#define TRK_NAME_LEN 20
#define MAX_RTE_POINTS 50
+#define MAX_ITEMS_PER_GROUP 12
/*
I suspect that these are actually
struct signature {
- uint8_t format, // 1 = track, 2 = waypoint, 3 = route
+ uint8_t format, // 1 = track, 2 = waypoint, 3 = route, 4 = iTrack
uint8_t version,
gpuint16 record_length
}
The v3 TRK_MAGIC doesn't have a length, probably because it wouldn't fit.
(It would be 0x200008)
-Still, they're usful in the code as a plain signature.
+Still, they're useful in the code as a plain signature.
*/
#define TRK_MAGIC 0x01030000L
#define TRK_MAGIC2 0x01021F70L
#define WPT_MAGIC 0x02020024L
+#define WPT_MAGIC2 0x02030024L // New for 2013. No visible diff?!
#define RTE_MAGIC 0x03030088L
#define EAST_SCALE 20038297.0 /* this is i1924_equ_axis*M_PI */
int16_t deltanorth;
} humminbird_trk_point_old_t;
+typedef struct group_header {
+ gbuint8 status;
+ gbuint8 icon;
+ gbuint16 depth;
+ gbuint32 time; /* a time_t, in UTC */
+ gbuint16 parent_idx;
+ gbuint16 reserved1;
+ gbuint16 first_body_index;
+ gbuint16 reserved2;
+ char name[WPT_NAME_LEN];
+} group_header_t;
+
+typedef struct group_body {
+ gbuint8 status;
+ gbuint8 icon;
+ gbuint16 next_idx;
+ gbuint16 item[MAX_ITEMS_PER_GROUP];
+} group_body_t;
+
+
static const char* humminbird_icons[] = {
"Normal", /* 0 */
"House", /* 1 */
static gbfile* fout;
static int waypoint_num;
static short_handle wptname_sh, rtename_sh, trkname_sh;
-static avltree_t* waypoints;
static humminbird_rte_t* humrte;
static int rte_num;
+static QMap<QString, waypoint*> map;
static
arglist_t humminbird_args[] = {
humminbird_rd_init(const char* fname)
{
fin = gbfopen_be(fname, "rb", MYNAME);
- waypoints = avltree_init(0, MYNAME);
}
static void
humminbird_rd_deinit(void)
{
- avltree_done(waypoints);
gbfclose(fin);
}
static void
humminbird_read_wpt(gbfile* fin)
{
-
humminbird_waypt_t w;
double guder;
int num_icons;
waypoint* wpt;
- char buff[10];
if (! gbfread(&w, 1, sizeof(w), fin)) {
fatal(MYNAME ": Unexpected end of file!\n");
wpt->icon_descr = humminbird_icons[w.icon];
}
- waypt_add(wpt);
+ // In newer versions, this is an enum (though it looks like a bitfield)
+ // that describes a sub-status
+ switch (w.status) {
+ case 0: // Waypoint not used. So why do we have one?
+ break;
+ case 1: // Waypoint permanent.
+ case 2: // Waypoint temporary.
+ case 3: // Waypoint man-overboard.
+ waypt_add(wpt);
+ break;
+ case 16: // Waypoint group header.
+ case 17: // Waypoint group body.
+ case 63: // Waypoint group invalid.
+ default:
+ break;
+ }
/* register the point over his internal Humminbird "Number" */
- snprintf(buff, sizeof(buff), "%d", w.num);
- avltree_insert(waypoints, buff, wpt);
+ QString buff = QString::number(w.num);
+ map[buff] = wpt;
}
static void
route_head* rte = NULL;
for (i = 0; i < hrte.count; i++) {
- waypoint* wpt;
+ const waypoint* wpt;
char buff[10];
hrte.points[i] = be_read16(&hrte.points[i]);
/* locate the point over his internal Humminbird "Number" */
snprintf(buff, sizeof(buff), "%d", hrte.points[i]);
- if (avltree_find(waypoints, buff, (const void**) &wpt)) {
+ if ((map.value(buff))) {
+ wpt = map.value(buff);
if (rte == NULL) {
rte = route_head_alloc();
route_add_head(rte);
switch (signature) {
case WPT_MAGIC:
+ case WPT_MAGIC2:
humminbird_read_wpt(fin);
break;
case RTE_MAGIC:
setshort_repeating_whitespace_ok(trkname_sh, 1);
setshort_defname(trkname_sh, "Track");
- waypoints = avltree_init(0, MYNAME);
-
waypoint_num = 0;
rte_num = 0;
}
static void
humminbird_wr_deinit(void)
{
- avltree_done(waypoints);
mkshort_del_handle(&wptname_sh);
mkshort_del_handle(&rtename_sh);
mkshort_del_handle(&trkname_sh);
waypoint* tmpwpt;
xasprintf(&key, "%s\01%.9f\01%.9f", wpt->shortname, wpt->latitude, wpt->longitude);
-
- if (! avltree_find(waypoints, key, (const void**)&tmpwpt)) {
+ if (!(tmpwpt = map[key])) {
tmpwpt = (waypoint*)wpt;
-
- avltree_insert(waypoints, key, wpt);
-
+ map[key] = (waypoint*) wpt;
tmpwpt->extra_data = gb_int2ptr(waypoint_num + 1); /* NOT NULL */
humminbird_write_waypoint(wpt);
} else {
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<gpx version="1.1" creator="GPSBabel - http://www.gpsbabel.org" xmlns="http://www.topografix.com/GPX/1/1" xmlns:h="http://humminbird.com">
+ <metadata>
+ <time>1970-01-01T00:00:00Z</time>
+ <bounds minlat="46.250304116" minlon="-93.734441604" maxlat="46.276782900" maxlon="-93.713062542"/>
+ </metadata>
+ <wpt lat="46.250304116" lon="-93.713062542">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:53:40Z</time>
+ <name>WP001</name>
+ <cmt>WP001</cmt>
+ <desc>WP001</desc>
+ <sym>Normal</sym>
+ </wpt>
+ <wpt lat="46.256467034" lon="-93.726159464">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:53:45Z</time>
+ <name>WP002</name>
+ <cmt>WP002</cmt>
+ <desc>WP002</desc>
+ <sym>Normal</sym>
+ </wpt>
+ <wpt lat="46.261850448" lon="-93.719503209">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:53:52Z</time>
+ <name>WP003</name>
+ <cmt>WP003</cmt>
+ <desc>WP003</desc>
+ <sym>Normal</sym>
+ </wpt>
+ <wpt lat="46.272229465" lon="-93.721641116">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:00Z</time>
+ <name>WP004</name>
+ <cmt>WP004</cmt>
+ <desc>WP004</desc>
+ <sym>Normal</sym>
+ </wpt>
+ <wpt lat="46.269638011" lon="-93.734441604">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:10Z</time>
+ <name>WP005</name>
+ <cmt>WP005</cmt>
+ <desc>WP005</desc>
+ <sym>Normal</sym>
+ </wpt>
+ <wpt lat="46.276782900" lon="-93.724317990">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:18Z</time>
+ <name>WP006</name>
+ <cmt>WP006</cmt>
+ <desc>WP006</desc>
+ <sym>Normal</sym>
+ </wpt>
+ <wpt lat="46.266143091" lon="-93.723958678">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:26Z</time>
+ <name>WP007</name>
+ <cmt>WP007</cmt>
+ <desc>WP007</desc>
+ <sym>Normal</sym>
+ </wpt>
+ <wpt lat="46.262834858" lon="-93.732932494">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:34Z</time>
+ <name>WP008</name>
+ <cmt>WP008</cmt>
+ <desc>WP008</desc>
+ <sym>Normal</sym>
+ </wpt>
+ <wpt lat="46.254392034" lon="-93.716574817">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:49Z</time>
+ <name>WP009</name>
+ <cmt>WP009</cmt>
+ <desc>WP009</desc>
+ <sym>Normal</sym>
+ </wpt>
+ <wpt lat="46.270541297" lon="-93.726770294">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:57Z</time>
+ <name>WP010</name>
+ <cmt>WP010</cmt>
+ <desc>WP010</desc>
+ <sym>Normal</sym>
+ </wpt>
+ <wpt lat="46.266080791" lon="-93.718991190">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:55:06Z</time>
+ <name>WP011</name>
+ <cmt>WP011</cmt>
+ <desc>WP011</desc>
+ <sym>Normal</sym>
+ </wpt>
+ <rte>
+ <name>RT001</name>
+ <rtept lat="46.250304116" lon="-93.713062542">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:53:40Z</time>
+ <name>WP001</name>
+ <cmt>WP001</cmt>
+ <desc>WP001</desc>
+ <sym>Normal</sym>
+ </rtept>
+ <rtept lat="46.256467034" lon="-93.726159464">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:53:45Z</time>
+ <name>WP002</name>
+ <cmt>WP002</cmt>
+ <desc>WP002</desc>
+ <sym>Normal</sym>
+ </rtept>
+ <rtept lat="46.261850448" lon="-93.719503209">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:53:52Z</time>
+ <name>WP003</name>
+ <cmt>WP003</cmt>
+ <desc>WP003</desc>
+ <sym>Normal</sym>
+ </rtept>
+ <rtept lat="46.272229465" lon="-93.721641116">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:00Z</time>
+ <name>WP004</name>
+ <cmt>WP004</cmt>
+ <desc>WP004</desc>
+ <sym>Normal</sym>
+ </rtept>
+ <rtept lat="46.269638011" lon="-93.734441604">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:10Z</time>
+ <name>WP005</name>
+ <cmt>WP005</cmt>
+ <desc>WP005</desc>
+ <sym>Normal</sym>
+ </rtept>
+ <rtept lat="46.276782900" lon="-93.724317990">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:18Z</time>
+ <name>WP006</name>
+ <cmt>WP006</cmt>
+ <desc>WP006</desc>
+ <sym>Normal</sym>
+ </rtept>
+ <rtept lat="46.266143091" lon="-93.723958678">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:26Z</time>
+ <name>WP007</name>
+ <cmt>WP007</cmt>
+ <desc>WP007</desc>
+ <sym>Normal</sym>
+ </rtept>
+ <rtept lat="46.262834858" lon="-93.732932494">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:34Z</time>
+ <name>WP008</name>
+ <cmt>WP008</cmt>
+ <desc>WP008</desc>
+ <sym>Normal</sym>
+ </rtept>
+ <rtept lat="46.254392034" lon="-93.716574817">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:49Z</time>
+ <name>WP009</name>
+ <cmt>WP009</cmt>
+ <desc>WP009</desc>
+ <sym>Normal</sym>
+ </rtept>
+ <rtept lat="46.270541297" lon="-93.726770294">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:57Z</time>
+ <name>WP010</name>
+ <cmt>WP010</cmt>
+ <desc>WP010</desc>
+ <sym>Normal</sym>
+ </rtept>
+ <rtept lat="46.266080791" lon="-93.718991190">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:55:06Z</time>
+ <name>WP011</name>
+ <cmt>WP011</cmt>
+ <desc>WP011</desc>
+ <sym>Normal</sym>
+ </rtept>
+ </rte>
+</gpx>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<gpx version="1.1" creator="GPSBabel - http://www.gpsbabel.org" xmlns="http://www.topografix.com/GPX/1/1" xmlns:h="http://humminbird.com">
+ <metadata>
+ <time>1970-01-01T00:00:00Z</time>
+ <bounds minlat="46.250304116" minlon="-93.734441604" maxlat="46.276782900" maxlon="-93.713062542"/>
+ </metadata>
+ <wpt lat="46.250304116" lon="-93.713062542">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:53:40Z</time>
+ <name>WP001</name>
+ <cmt>WP001</cmt>
+ <desc>WP001</desc>
+ <sym>Normal</sym>
+ </wpt>
+ <wpt lat="46.256467034" lon="-93.726159464">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:53:45Z</time>
+ <name>WP002</name>
+ <cmt>WP002</cmt>
+ <desc>WP002</desc>
+ <sym>Normal</sym>
+ </wpt>
+ <wpt lat="46.261850448" lon="-93.719503209">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:53:52Z</time>
+ <name>WP003</name>
+ <cmt>WP003</cmt>
+ <desc>WP003</desc>
+ <sym>Normal</sym>
+ </wpt>
+ <wpt lat="46.272229465" lon="-93.721641116">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:00Z</time>
+ <name>WP004</name>
+ <cmt>WP004</cmt>
+ <desc>WP004</desc>
+ <sym>Normal</sym>
+ </wpt>
+ <wpt lat="46.269638011" lon="-93.734441604">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:10Z</time>
+ <name>WP005</name>
+ <cmt>WP005</cmt>
+ <desc>WP005</desc>
+ <sym>Normal</sym>
+ </wpt>
+ <wpt lat="46.276782900" lon="-93.724317990">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:18Z</time>
+ <name>WP006</name>
+ <cmt>WP006</cmt>
+ <desc>WP006</desc>
+ <sym>Normal</sym>
+ </wpt>
+ <wpt lat="46.266143091" lon="-93.723958678">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:26Z</time>
+ <name>WP007</name>
+ <cmt>WP007</cmt>
+ <desc>WP007</desc>
+ <sym>Normal</sym>
+ </wpt>
+ <wpt lat="46.262834858" lon="-93.732932494">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:34Z</time>
+ <name>WP008</name>
+ <cmt>WP008</cmt>
+ <desc>WP008</desc>
+ <sym>Normal</sym>
+ </wpt>
+ <wpt lat="46.254392034" lon="-93.716574817">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:49Z</time>
+ <name>WP009</name>
+ <cmt>WP009</cmt>
+ <desc>WP009</desc>
+ <sym>Normal</sym>
+ </wpt>
+ <wpt lat="46.270541297" lon="-93.726770294">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:57Z</time>
+ <name>WP010</name>
+ <cmt>WP010</cmt>
+ <desc>WP010</desc>
+ <sym>Normal</sym>
+ </wpt>
+ <wpt lat="46.266080791" lon="-93.718991190">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:55:06Z</time>
+ <name>WP011</name>
+ <cmt>WP011</cmt>
+ <desc>WP011</desc>
+ <sym>Normal</sym>
+ </wpt>
+ <rte>
+ <name>RT001</name>
+ <rtept lat="46.250304116" lon="-93.713062542">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:53:40Z</time>
+ <name>WP001</name>
+ <cmt>WP001</cmt>
+ <desc>WP001</desc>
+ <sym>Normal</sym>
+ </rtept>
+ <rtept lat="46.256467034" lon="-93.726159464">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:53:45Z</time>
+ <name>WP002</name>
+ <cmt>WP002</cmt>
+ <desc>WP002</desc>
+ <sym>Normal</sym>
+ </rtept>
+ <rtept lat="46.261850448" lon="-93.719503209">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:53:52Z</time>
+ <name>WP003</name>
+ <cmt>WP003</cmt>
+ <desc>WP003</desc>
+ <sym>Normal</sym>
+ </rtept>
+ <rtept lat="46.272229465" lon="-93.721641116">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:00Z</time>
+ <name>WP004</name>
+ <cmt>WP004</cmt>
+ <desc>WP004</desc>
+ <sym>Normal</sym>
+ </rtept>
+ <rtept lat="46.269638011" lon="-93.734441604">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:10Z</time>
+ <name>WP005</name>
+ <cmt>WP005</cmt>
+ <desc>WP005</desc>
+ <sym>Normal</sym>
+ </rtept>
+ <rtept lat="46.276782900" lon="-93.724317990">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:18Z</time>
+ <name>WP006</name>
+ <cmt>WP006</cmt>
+ <desc>WP006</desc>
+ <sym>Normal</sym>
+ </rtept>
+ <rtept lat="46.266143091" lon="-93.723958678">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:26Z</time>
+ <name>WP007</name>
+ <cmt>WP007</cmt>
+ <desc>WP007</desc>
+ <sym>Normal</sym>
+ </rtept>
+ <rtept lat="46.262834858" lon="-93.732932494">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:34Z</time>
+ <name>WP008</name>
+ <cmt>WP008</cmt>
+ <desc>WP008</desc>
+ <sym>Normal</sym>
+ </rtept>
+ <rtept lat="46.254392034" lon="-93.716574817">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:49Z</time>
+ <name>WP009</name>
+ <cmt>WP009</cmt>
+ <desc>WP009</desc>
+ <sym>Normal</sym>
+ </rtept>
+ <rtept lat="46.270541297" lon="-93.726770294">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:54:57Z</time>
+ <name>WP010</name>
+ <cmt>WP010</cmt>
+ <desc>WP010</desc>
+ <sym>Normal</sym>
+ </rtept>
+ <rtept lat="46.266080791" lon="-93.718991190">
+ <ele>0.000000</ele>
+ <time>2008-06-14T16:55:06Z</time>
+ <name>WP011</name>
+ <cmt>WP011</cmt>
+ <desc>WP011</desc>
+ <sym>Normal</sym>
+ </rtept>
+ </rte>
+</gpx>
gpsbabel -i gpx -f ${TMPDIR}/combo.gpx -o humminbird -F ${TMPDIR}/funky.hwr -o humminbird_ht -F ${TMPDIR}/funky.ht
bincompare ${REFERENCE}/humminbird.hwr ${TMPDIR}/funky.hwr
bincompare ${REFERENCE}/track/humminbird.ht ${TMPDIR}/funky.ht
+
+# In 2012, Humminbird changed their format in incompatible ways. We call them
+# v2 and v3 but we don't really know that they have names. The version number
+# internally didn't change.
+
+gpsbabel -i humminbird -f ${REFERENCE}/humminbird-rte-v2.hwr -o gpx,humminbirdextensions=1 -F ${TMPDIR}/humminbird-rte-v2~gpx.gpx
+compare ${REFERENCE}/humminbird-rte-v2~gpx.gpx ${TMPDIR}/humminbird-rte-v2~gpx.gpx
+
+gpsbabel -i humminbird -f ${REFERENCE}/humminbird-rte-v3.hwr -o gpx,humminbirdextensions=1 -F ${TMPDIR}/humminbird-rte-v3~gpx.gpx
+compare ${REFERENCE}/humminbird-rte-v3~gpx.gpx ${TMPDIR}/humminbird-rte-v3~gpx.gpx